package org.mtmi.ui.scenes;

import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.widgets.Shell;

/**
 * AnimationManager is in charges of animating visuals controls, thru scene redrawing.
 * 
 */
public class AnimationManager implements DisposeListener
{
	private static final int DELAY=30; //animation DELAY (ms)
	
	/** global animation status */
	private static final boolean ANIMATED=false;
	
	private class ATask extends TimerTask
	{
		private long t=-1;
		public ATask() {
			t = System.currentTimeMillis();
		}
		@Override
		public void run() {
			shell.getDisplay().syncExec( new Runnable() {
				@Override
				public void run() {
					long d= System.currentTimeMillis()-t;
					//TODO: debug System.out.println("  AnimationTask d="+(d)+"ms");
					if( !shell.isDisposed() && timer!=null && anims.size()>0 ) {
						long t0 = System.currentTimeMillis();
						IAnimated a[] = anims.toArray( new IAnimated[anims.size()] );
						for( int i=0; i<a.length; i++ ) {
							if( !a[i].animationStep() ) {
								anims.remove( a[i] );
							}
						}
						if( anims.size()>0 ) {
							SceneManager.getDefault().getScene().redraw();
							//SceneManager.getDefault().getScene().update();
							timer.schedule( new ATask(), DELAY );
						} else {
							stop();
						}
						d = System.currentTimeMillis()-t0;
//TODO:debug						System.out.println("  AnimTask step+draw d="+d+"ms");
					}
				}
			});
			
		}
	}
	
	private ArrayList<IAnimated> anims;
	private Timer timer;
	private Shell shell;
	private static AnimationManager instance;
	
	public static AnimationManager getDefault() { return instance; }
	
	public AnimationManager( Shell s ) {
		if( instance!= null ) throw new IllegalStateException("SceneManager already instanciated"); //$NON-NLS-1$
		instance=this;
		shell = s;
		anims = new ArrayList<IAnimated>();
	}
	
	/**@return true if animation is available, false otherwise */
	public boolean isAnimated() { return ANIMATED; }
	
	/**
	 * Add animation for the given object, when {@link IAnimated#animationStep()} returns false,
	 * the object is automatically removed from animation manager.
	 * @param a object to animate
	 * @return true if animation is engaged, false if no animation can be run.
	 */
	public boolean add( IAnimated a ) {
		if( ANIMATED ) {
			anims.add( a );
			if( anims.size() == 1) {
				start();
			}
		}
	     return ANIMATED;
	}
	
	/** remove an object, see add() method */
	public void remove( IAnimated a ) {
		if( ANIMATED ) {
			if( anims.remove( a ) ) {
				if( anims.size()==0 ) {
					stop();
				}
			}
		}
	}
	
	private void start() {
		timer = new Timer("AnimationManager");
		timer.schedule( new ATask(), DELAY );
	}
	
	private void stop() {
		if( timer!=null ) {
			timer.cancel();
			timer=null;
		}
	}
	
	@Override
	public void widgetDisposed(DisposeEvent e) {
		stop();
	}
}
